package test.example.service;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slim3.memcache.Memcache;

import test.example.auth.GoogleConnection;
import test.example.dto.DocumentAclEntryDto;
import test.example.dto.DocumentListEntryDto;

import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gdata.client.authn.oauth.OAuthException;
import com.google.gdata.client.docs.DocsService;
import com.google.gdata.data.acl.AclEntry;
import com.google.gdata.data.acl.AclFeed;
import com.google.gdata.data.acl.AclScope;
import com.google.gdata.data.docs.DocumentListEntry;
import com.google.gdata.data.docs.DocumentListFeed;
import com.google.gdata.util.ServiceException;

/**
 * @author sugi
 * 
 */
public class DocumentService {

    private GoogleConnection conn = GoogleConnection.getInstance();
    private DocsService clientInstance = null;

    private final String GDOCS_FEED_URI =
        "https://docs.google.com/feeds/default/private/full/";

    private final String GDOCS_FEED_TYPE_FOLDER = "-/folder";
    private final String ROOT_FOLDER_ID = "root";

    public void applyGroupACL(HttpServletRequest request,
            HttpServletResponse response, String aclFeedLink) {
        //groupのemail list取得
        
        //emailListにaclFeedLinkで得られる権限と同じものを適用する。
            //ownerの上書きは行わない！！
    }

    /**
     * 
     * ACLFeedにAclScope.Type.GROUP の共有設定を含むFolderのリストを返します。
     * １０件ずつ処理するために、crawlSession文字列（mailAddress+timeinMilli） を使用します。
     * callback関数の中でcrawlSessionを指定できるように！ crawlSessionがnullの場合は処理が終了したことを意味します。
     * 
     * @param request
     * @param response
     * @param parentFolderId
     * @return
     * @throws OAuthException
     * @throws IOException
     * @throws ServiceException
     */
    public List<DocumentListEntryDto> crawlGroupDocsFeed(
            HttpServletRequest request, HttpServletResponse response,
            String crawlSession, String parentFolderId) throws OAuthException,
            IOException, ServiceException {

        // crawlSession文字列から、途中結果を取得
        List<DocumentListEntryDto> allFolder =
            Memcache.get(crawlSession + "_preList");
        Integer index = Memcache.get(crawlSession + "_index");
        // parentFolderIdを取得
        if (parentFolderId != null) {
            // 前回と異なるので無条件にallFolderをクリアする。
            if(!parentFolderId.equals(Memcache.get(crawlSession + "_parentFolder")))
            allFolder = null;
        }
        if (parentFolderId == null || parentFolderId =="") {
            parentFolderId = Memcache.get(crawlSession + "_parentFolder");
        }
        if (parentFolderId == null|| parentFolderId =="") {
            parentFolderId = ROOT_FOLDER_ID;
            allFolder = null;
        }

        // Memcacheの初期化,crawlSessionの作成
        UserService userService = UserServiceFactory.getUserService();
        String mailAddress = userService.getCurrentUser().getEmail();
        crawlSession = mailAddress + System.currentTimeMillis();

        if (allFolder == null) {
            allFolder = getDocsFeed(request, response, parentFolderId);
        }
        if (index == null) {
            index = -1;
        }
        
        if(allFolder.size()==0){
            crawlSession = null;
        }

        List<DocumentListEntryDto> resultList =
            new ArrayList<DocumentListEntryDto>();
        // 1件ずつ処理する。crawlの再開点はMemcacheから取得したindex
        int lastIndex = 0;
        for (int i = index + 1; i < Math.min(allFolder.size(), index + 2); i++) {
            DocumentListEntryDto folder = allFolder.get(i);
            // aclFeedの取得
            AclFeed aclFeedResult =
                getClient(request, response).getFeed(
                    new URL(folder.getAclFeedLink()),
                    AclFeed.class);
            // groupの共有権限が存在するかチェックする
            // boolean hasGroupACL = false;
            List<DocumentAclEntryDto> aclEntryList =
                new ArrayList<DocumentAclEntryDto>();
            for (AclEntry entry : aclFeedResult.getEntries()) {
                DocumentAclEntryDto entryDto = new DocumentAclEntryDto();
                entryDto.setId(entry.getId());
                entryDto.setAclEditLink(entry.getEditLink().getHref());
                entryDto.setRole(entry.getRole().getValue());
                entryDto.setScopeType(entry.getScope().getType().toString());
                entryDto.setScopeValue(entry.getScope().getValue());
                aclEntryList.add(entryDto);
            }
            folder.setAclEntryList(aclEntryList);
            resultList.add(folder);
            
            // crawlの終了処理
//            if (i == allFolder.size() - 1)
                crawlSession = null;
            lastIndex = i;
        }
        if (crawlSession != null) {
            Memcache.put(crawlSession + "_preList", allFolder);
            Memcache.put(crawlSession + "_index", lastIndex);
            Memcache.put(crawlSession + "_parentFolder", parentFolderId);
        } else {
        }
        request.setAttribute("crawlSession", crawlSession);
        System.out.println("endOfCrawl" + crawlSession);
        return resultList;
    }

    private DocsService getClient(HttpServletRequest request,
            HttpServletResponse response) throws OAuthException, IOException {
        if (clientInstance == null) {
            conn.connectionStart(request, response);
            clientInstance = conn.getMyService();
        }
        return this.clientInstance;
    }

    private List<DocumentListEntryDto> getDocsFeed(HttpServletRequest request,
            HttpServletResponse response, String parentFolderId)
            throws OAuthException, IOException, ServiceException {
        DocsService client = getClient(request, response);

        URL foldersFeedUri =
            new URL(GDOCS_FEED_URI
                + "folder:"
                + parentFolderId
                + "/contents/"
                + GDOCS_FEED_TYPE_FOLDER);
        DocumentListFeed resultFeed =
            client.getFeed(foldersFeedUri, DocumentListFeed.class);
        List<DocumentListEntry> entries = resultFeed.getEntries();

        List<DocumentListEntryDto> result =
            new ArrayList<DocumentListEntryDto>();
        for (DocumentListEntry e : entries) {
            DocumentListEntryDto dto = new DocumentListEntryDto();
            dto.setAclFeedLink(e.getAclFeedLink().getHref());
            dto.setId(e.getResourceId().split(":")[1]);
            dto.setTitle(e.getTitle().getPlainText());
            result.add(dto);
            System.out.println(e.getTitle().getPlainText());
        }
        if (entries.size() == 0) {
            System.out.println("no hit");
        }
        return result;
    }

}
